#!/bin/bash

echo "#Generating the .spice power grid benchmark and .reg region information and .flp file"
echo "#Author: Min Li, Contact: mli46@wisc.edu"
echo -ne "#Generated Date: "
date
echo 

export GRID_CNT=$1 ## for the long side

export PL_FILE=$HSTA_BENCHMARK_DIR\/$HSTA_BENCHMARK"-mPL.pl"
export REGION_FILE=$HSTA_BENCHMARK_DIR\/$HSTA_BENCHMARK".reg"
export PG_BENCH_FILE=$HSTA_BENCHMARK_DIR\/$HSTA_BENCHMARK".spice"
export FLP_BENCH_FILE=$HSTA_BENCHMARK_DIR\/$HSTA_BENCHMARK".flp"
echo "Region file is "$REGION_FILE
echo "Power Grid bench file is "$PG_BENCH_FILE
echo "Hotspot placement bench file is "$FLP_BENCH_FILE

## Find the four corners of a placement floorplan
OIFS="$IFS"
IFS=' '
set -- $(awk 'BEGIN {max_x=0; min_x=1000000; max_y=0; min_y=1000000;} 
  IF NR>4 {
      if ($3>max_y) 
          max_y=$3 
      if ($3<min_y) 
          min_y=$3 
      if ($2>max_x) 
          max_x=$2 
      if ($2<min_x) 
          min_x=$2 
} 
END {print max_y, min_y, max_x, min_x}' $PL_FILE)
IFS="$OIFS"
max_y=$1 min_y=$2 max_x=$3 min_x=$4

echo "Processing Placement benchmark..."
echo "max_y: "$max_y
echo "min_y: "$min_y
echo "max_x: "$max_x
echo "min_x: "$min_x
echo

let "grid_width=$max_y-$min_y"
let "grid_length=$max_x-$min_x"

flag=0;
if [ "$grid_width" -gt "$grid_length" ]
then
    temp=$grid_width
    flag=1
else
    temp=$grid_length
fi

echo $temp
let "step_size=$temp / $GRID_CNT + 1"
#echo "hoho "$step_size

if [ "$flag" -eq 1 ]
then
    Y_grid_cnt=$GRID_CNT
    Y_step_size=$step_size
    ## Odd grid number
    let "X_grid_cnt=$grid_length / $step_size"
    let "tmp=$X_grid_cnt % 2"
    if [ $tmp -eq 1 ]
    then
        let "X_grid_cnt=$X_grid_cnt+1"
    fi
    let "tmp=$grid_length/$X_grid_cnt"
    let "tmp=$tmp % 2"
    if [ $tmp -eq 1 ]
    then
        let "X_step_size=$grid_length/$X_grid_cnt+1"
    else
        let "X_step_size=$grid_length/$X_grid_cnt"
    fi
else
    X_grid_cnt=$GRID_CNT
    X_step_size=$step_size
    ## Odd grid number
    let "Y_grid_cnt=$grid_width / $step_size"
    let "tmp=$Y_grid_cnt % 2"
    if [ $tmp -eq 1 ]
    then
        let "Y_grid_cnt=$Y_grid_cnt+1"
    fi
    let "tmp=$grid_width/$Y_grid_cnt"
    let "tmp=$tmp % 2"
    if [ $tmp -eq 1 ]
    then
        let "Y_step_size=$grid_width/$Y_grid_cnt+1"
    else
        let "Y_step_size=$grid_width/$Y_grid_cnt"
    fi
fi

let "VSS_X_GRID_OFFSET=$X_step_size/2"
let "VSS_Y_GRID_OFFSET=$Y_step_size/2"
echo "X grid count is: "$X_grid_cnt
echo "Y grid count is: "$Y_grid_cnt
echo "X grid step size is: "$X_step_size
echo "Y grid step size is: "$Y_step_size
echo


## move all coordinates to the lower-left corner <0,0> 
awk -v ll_x=$min_x -v ll_y=$min_y '{if(NR>4) {print $1, $2-ll_x, $3-ll_y }}' $PL_FILE > $HSTA_BENCHMARK_DIR/out_tmp.txt


## Generate the .reg file
rm -rf $REGION_FILE
echo "Generating .reg file..."
let "tot_reg_cnt = $X_grid_cnt * $Y_grid_cnt"
HSTA_REG_CNT=$tot_reg_cnt
echo $tot_reg_cnt > $REGION_FILE
echo "Y step size "$Y_step_size
awk -v xst=$X_step_size -v yst=$Y_step_size -v xgc=$X_grid_cnt -v TRC=$tot_reg_cnt \
'{reg_id=int($2/xst) + int($3/yst)*xgc + 1; if(reg_id>TRC) {printf("%d %s\n", TRC, $1)} else {printf("%d %s\n", reg_id, $1)}}' \
$HSTA_BENCHMARK_DIR/out_tmp.txt > $HSTA_BENCHMARK_DIR/out_tmp1.txt
sort -t " " -nk1 $HSTA_BENCHMARK_DIR/out_tmp1.txt > $HSTA_BENCHMARK_DIR/out_tmp2.txt

awk 'BEGIN {reg_cnt=1; printf("region1\n")} \
{
      if ($1==reg_cnt) 
          {printf "%s\n", $2}
      else
           {printf "!\nregion%d\n", $1; printf "%s\n", $2; reg_cnt=$1}
} ' $HSTA_BENCHMARK_DIR/out_tmp2.txt >> $REGION_FILE

echo "!" >> $REGION_FILE
echo "#end" >> $REGION_FILE

#rm -rf $HSTA_BENCHMARK_DIR/out_tmp*
## Generate the .flp file
rm -rf $FLP_BENCH_FILE
echo "# Floorplan of $BENCHMARK" >> $FLP_BENCH_FILE
echo "# Line Format: <unit-name>\t<width>\t<height>\t<left-x>\t<bottom-y>" >> $FLP_BENCH_FILE
echo "# all dimensions are in meters" >> $FLP_BENCH_FILE
echo "" >> $FLP_BENCH_FILE

factor=0.000001
for (( i=1; i<=$tot_reg_cnt; i++ ))
do 
    let "x_pos = ($i-1) % $X_grid_cnt"
    let "y_pos = ($i-1) / $X_grid_cnt"
    if [ $x_pos -eq 0 ]
    then
        x_pos_t=0
    else
        x_pos_t=$(echo "$x_pos*$X_step_size*$factor" | bc)
    fi
    if [ $y_pos -eq 0 ]
    then
        y_pos_t=0
    else
        y_pos_t=$(echo "$y_pos*$Y_step_size*$factor" | bc)
    fi
    
    t_x_step_size=$(echo "$X_step_size*$factor" | bc)
    t_y_step_size=$(echo "$Y_step_size*$factor" | bc)
    
    echo "region$i $t_x_step_size $t_y_step_size $x_pos_t $y_pos_t" >> $FLP_BENCH_FILE
done


## Generate the .spice file, parasitics are extracted from the library specified in ~/.synopsis_pt.script
echo "Generating .spice file..."

## Compute VSS number 2X2 "bigger" grid size
let "X_VSS_CNT=$X_grid_cnt/2"
let "Y_VSS_CNT=$Y_grid_cnt/2"

rm -rf $PG_BENCH_FILE

## Print out VDD, VSS and their resistance information
tot_VSS_CNT=0
for ((i = 0; i<$Y_VSS_CNT; i++))
do
    let "y_axis=$i * $Y_step_size * 2"
    for ((j = 0; j<$X_VSS_CNT; j++))
    do
        let "x_axis=$j * $X_step_size * 2"
        ## VDD network
        echo "v"$tot_VSS_CNT" _X_n3_"$x_axis"_"$y_axis "0" $VDD >> $PG_BENCH_FILE
        echo "rr"$tot_VSS_CNT" n3_"$x_axis"_"$y_axis" _X_n3_"$x_axis"_"$y_axis" 0.5" >> $PG_BENCH_FILE
        let "tot_VSS_CNT=$tot_VSS_CNT+1"
        ## VSS network
        let "temp1=$x_axis+$VSS_X_GRID_OFFSET"
        let "temp2=$y_axis+$VSS_Y_GRID_OFFSET"
        echo "v"$tot_VSS_CNT" _X_n2_"$temp1"_"$temp2" 0 0" >> $PG_BENCH_FILE
        echo "rr"$tot_VSS_CNT" n2_"$temp1"_"$temp2" _X_n2_"$temp1"_"$temp2" 0.5" >> $PG_BENCH_FILE
        let "tot_VSS_CNT=$tot_VSS_CNT+1"
    done
done

X_norm_res=$(echo "$res_per_unit_len * $X_step_size" | bc)
Y_norm_res=$(echo "$res_per_unit_len * $Y_step_size" | bc)
#let "Y_norm_res=$res_per_unit_len * $Y_step_size"

## Print out the normal resistence information 
echo "* layer: M1, VDD net: 1" >> $PG_BENCH_FILE
tot_RES_CNT=0
for ((i = 0; i<$Y_grid_cnt; i++))
do
    let "y1_axis=$i * $Y_step_size"
    y2_axis=$y1_axis
    for ((j = 0; j<$X_grid_cnt-1; j++))
    do 
        let "x1_axis=$j * $X_step_size"
        let "x2_axis=($j + 1) * $X_step_size"
        echo "R"$tot_RES_CNT" n1_"$x1_axis"_"$y1_axis" n1_"$x2_axis"_"$y2_axis $X_norm_res >> $PG_BENCH_FILE
        let "tot_RES_CNT=$tot_RES_CNT+1"
    done
done

echo "* layer: M3, VDD net: 3" >> $PG_BENCH_FILE
for ((i = 0; i<$X_grid_cnt; i++))
do
    let "x1_axis=$i * $X_step_size"
    let "x2_axis=$x1_axis"
    for ((j = 0; j<$Y_grid_cnt-1; j++))
    do 
        let "y1_axis=$j * $Y_step_size"
        let "y2_axis=($j + 1) * $Y_step_size"
        echo "R"$tot_RES_CNT" n3_"$x1_axis"_"$y1_axis" n3_"$x2_axis"_"$y2_axis $X_norm_res >> $PG_BENCH_FILE
        let "tot_RES_CNT=$tot_RES_CNT+1"
    done
done

echo "* layer: M0, GND net: 0" >> $PG_BENCH_FILE
for ((i = 0; i<$Y_grid_cnt; i++))
do
    let "y1_axis=$i * $Y_step_size + $VSS_Y_GRID_OFFSET"
    y2_axis=$y1_axis
    for ((j = 0; j<$X_grid_cnt-1; j++))
    do 
        let "x1_axis=$j * $X_step_size + $VSS_X_GRID_OFFSET"
        let "x2_axis=($j + 1) * $X_step_size + $VSS_X_GRID_OFFSET"
        echo "R"$tot_RES_CNT" n0_"$x1_axis"_"$y1_axis" n0_"$x2_axis"_"$y2_axis $Y_norm_res >> $PG_BENCH_FILE
        let "tot_RES_CNT=$tot_RES_CNT+1"
    done
done

echo "* layer: M2, GND net: 2" >> $PG_BENCH_FILE
for ((i = 0; i<$X_grid_cnt; i++))
do
    let "x1_axis=$i * $X_step_size + $VSS_X_GRID_OFFSET"
    x2_axis=$x1_axis
    for ((j = 0; j<$Y_grid_cnt-1; j++))
    do 
        let "y1_axis=$j * $Y_step_size + $VSS_Y_GRID_OFFSET"
        let "y2_axis=($j + 1) * $Y_step_size + $VSS_Y_GRID_OFFSET"
        echo "R"$tot_RES_CNT" n2_"$x1_axis"_"$y1_axis" n2_"$x2_axis"_"$y2_axis $X_norm_res >> $PG_BENCH_FILE
        let "tot_RES_CNT=$tot_RES_CNT+1"
    done
done


## Print out VIA information
echo "* vias from: 1 to 3" >> $PG_BENCH_FILE
tot_VIA_CNT=0
for ((i = 0; i<$Y_grid_cnt; i++))
do
    let "y1_axis=$i * $Y_step_size"
    for ((j = 0; j<$X_grid_cnt; j++))
    do
        let "x1_axis=$j * $X_step_size"
        echo "V"$tot_VIA_CNT" n1_"$x1_axis"_"$y1_axis" n3_"$x1_axis"_"$y1_axis" 0.0" >> $PG_BENCH_FILE
        let "tot_VIA_CNT=$tot_VIA_CNT+1"
    done
done 

echo "* vias from: 0 to 2" >> $PG_BENCH_FILE
for ((i = 0; i<$Y_grid_cnt; i++))
do
    let "y1_axis=$i * $Y_step_size + $VSS_Y_GRID_OFFSET"
    for ((j = 0; j<$X_grid_cnt; j++))
    do
        let "x1_axis=$j * $X_step_size + $VSS_X_GRID_OFFSET"
        echo "V"$tot_VIA_CNT" n0_"$x1_axis"_"$y1_axis" n2_"$x1_axis"_"$y1_axis" 0.0" >> $PG_BENCH_FILE
        let "tot_VIA_CNT=$tot_VIA_CNT+1"
    done
done 

## Print out current source information
CS=0.005
tot_CS_CNT=0
echo "* current source" >> $PG_BENCH_FILE
for ((i = 0; i<$Y_VSS_CNT; i++))
do
    let "y_axis=$i * $Y_step_size * 2 + $Y_step_size"
    for ((j = 0; j<$X_VSS_CNT; j++))
    do
        let "x_axis=$j * $X_step_size * 2 + $X_step_size"
        let "temp1=$x_axis+$VSS_X_GRID_OFFSET"
        let "temp2=$y_axis+$VSS_Y_GRID_OFFSET"
        ## VDD current source
        echo "iB"$tot_CS_CNT"_v n1_"$x_axis"_"$y_axis" 0 " $CS >> $PG_BENCH_FILE
        echo "iB"$tot_CS_CNT"_g 0 n0_"$temp1"_"$temp2 $CS >> $PG_BENCH_FILE
        let "tot_CS_CNT=$tot_CS_CNT+1"
    done
done

echo ".op" >> $PG_BENCH_FILE
echo ".end" >> $PG_BENCH_FILE
